package com.catsic.practice.listener;

import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.ExecutionListener;
import org.activiti.engine.delegate.TaskListener;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: zhangzf
 * @CreateTime: 2025-10-31  17:03
 * @Description: 动态分配任务监听器
 */
@Slf4j
@Component
public class NextAssigneeListener implements TaskListener {


    @Override
    public void notify(DelegateTask delegateTask) {
        String eventName = delegateTask.getEventName();
        String taskDefinitionKey = delegateTask.getTaskDefinitionKey();

        // 只在任务完成时处理
        if ("complete".equals(eventName)) {
            // 从流程实例获取变量，而不是任务局部变量
            String nextAssignee = getVariableFromProcessInstance(delegateTask, "nextAssignee");
            String rejectReason = getVariableFromProcessInstance(delegateTask, "rejectReason");

            log.info("任务完成监听器 - 任务: {}, 下一审批人: {}, 回退原因: {}",
                    taskDefinitionKey, nextAssignee, rejectReason);

            // 判断是正向流转还是回退
            if ("rollback".equals(rejectReason)) {
                handleRollbackAssignment(delegateTask, taskDefinitionKey, nextAssignee);
            } else {
                handleForwardAssignment(delegateTask, taskDefinitionKey, nextAssignee);
            }

            // 清空临时变量（从流程实例中清除）
            delegateTask.removeVariable("nextAssignee");
        }
    }

    /**
     * 从流程实例获取变量
     */
    private String getVariableFromProcessInstance(DelegateTask delegateTask, String variableName) {
        try {
            RuntimeService runtimeService =
                    ProcessEngines.getDefaultProcessEngine().getRuntimeService();
            String processInstanceId = delegateTask.getProcessInstanceId();
            return (String) runtimeService.getVariable(processInstanceId, variableName);
        } catch (Exception e) {
            log.error("从流程实例获取变量失败: {}", variableName, e);
            return null;
        }
    }
    /**
     * 从流程实例移除变量
     */
    private void removeVariableFromProcessInstance(DelegateTask delegateTask, String variableName) {
        try {
            RuntimeService runtimeService =
                    ProcessEngines.getDefaultProcessEngine().getRuntimeService();
            String processInstanceId = delegateTask.getProcessInstanceId();
            runtimeService.removeVariable(processInstanceId, variableName);
        } catch (Exception e) {
            log.error("从流程实例移除变量失败: {}", variableName, e);
        }
    }

    private void handleForwardAssignment(DelegateTask delegateTask, String currentTaskKey, String nextAssignee) {
        if (nextAssignee == null) {
            log.warn("正向流转时未指定下一审批人，当前任务: {}", currentTaskKey);
            return;
        }

        String nextNodeId = getNextNodeId(currentTaskKey);
        if (nextNodeId != null) {
            setAssigneeForNode(delegateTask, nextNodeId, nextAssignee);
            log.info("正向流转 - 为节点 {} 设置审批人: {}", nextNodeId, nextAssignee);
        }
    }

    private void handleRollbackAssignment(DelegateTask delegateTask, String currentTaskKey, String nextAssignee) {
        String rollbackNodeId = getRollbackNodeId(currentTaskKey);

        if (rollbackNodeId == null) {
            log.error("无法确定回退目标节点，当前任务: {}", currentTaskKey);
            return;
        }

        String actualAssignee = nextAssignee != null ? nextAssignee : getDefaultAssigneeForRollback(rollbackNodeId);

        if (actualAssignee != null) {
            setAssigneeForNode(delegateTask, rollbackNodeId, actualAssignee);
            log.info("回退流转 - 为回退目标节点 {} 设置审批人: {}", rollbackNodeId, actualAssignee);

            // 确保回退目标节点的所有必要变量都已设置
            ensureRollbackVariables(delegateTask, rollbackNodeId, actualAssignee);
        } else {
            log.error("回退流转 - 无法确定回退目标节点的审批人, 当前任务: {}, 回退目标: {}",
                    currentTaskKey, rollbackNodeId);
        }
    }

    /**
     * 确保回退目标节点的所有必要变量都已设置
     */
    private void ensureRollbackVariables(DelegateTask delegateTask, String rollbackNodeId, String assignee) {
        // 设置目标节点的审批人变量
        setAssigneeForNode(delegateTask, rollbackNodeId, assignee);

        // 如果是回退到自身，还需要设置其他可能需要的变量
        if (rollbackNodeId.equals(delegateTask.getTaskDefinitionKey())) {
            log.info("回退到自身节点: {}", rollbackNodeId);
            // 可以在这里设置其他回退相关的变量
        }
    }

    private void setAssigneeForNode(DelegateTask delegateTask, String nodeId, String assignee) {
        String variableName = getAssigneeVariableName(nodeId);
        if (variableName != null) {
            delegateTask.setVariable(variableName, assignee);
            log.debug("设置变量: {} = {}", variableName, assignee);
        }
    }

    /**
     * 根据节点ID获取对应的审批人变量名
     */
    private String getAssigneeVariableName(String nodeId) {
        switch (nodeId) {
            case "policyRegulationsApproval":
                return "policyRegulationsAssignee";
            case "responsibleDepartmentApproval":
                return "responsibleDepartmentAssignee";
            case "agencyResponse":
                return "agencyAssignee";
            case "responsibleDepartmentReview":
                return "reviewAssignee";
            case "departmentLeaderApproval":
                return "leaderAssignee";
            case "hotlineLeaderApproval":
                return "hotlineLeaderAssignee";
            default:
                log.warn("未知的节点ID: {}", nodeId);
                return null;
        }
    }

    private String getNextNodeId(String currentTaskKey) {
        switch (currentTaskKey) {
            case "policyRegulationsApproval": return "responsibleDepartmentApproval";
            case "responsibleDepartmentApproval": return "agencyResponse";
            case "agencyResponse": return "responsibleDepartmentReview";
            case "responsibleDepartmentReview": return "departmentLeaderApproval";
            case "departmentLeaderApproval": return "hotlineLeaderApproval";
            default: return null;
        }
    }

    private String getRollbackNodeId(String currentTaskKey) {
        switch (currentTaskKey) {
            case "policyRegulationsApproval": return "policyRegulationsApproval";
            case "responsibleDepartmentApproval": return "policyRegulationsApproval";
            case "agencyResponse": return "responsibleDepartmentApproval";
            case "responsibleDepartmentReview": return "agencyResponse";
            case "departmentLeaderApproval": return "responsibleDepartmentReview";
            case "hotlineLeaderApproval": return "departmentLeaderApproval";
            default: return null;
        }
    }

    private String getDefaultAssigneeForRollback(String rollbackNodeId) {
        switch (rollbackNodeId) {
            case "policyRegulationsApproval": return "policy_default_user";
            case "responsibleDepartmentApproval": return "responsible_default_user";
            case "agencyResponse": return "agency_default_user";
            case "responsibleDepartmentReview": return "review_default_user";
            case "departmentLeaderApproval": return "leader_default_user";
            default: return null;
        }
    }
}
